/**
 * @file Hive account type definitions.
 * @author Johan Nordberg <code@johan-nordberg.com>
 * @license
 * Copyright (c) 2017 Johan Nordberg. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *  1. Redistribution of source code must retain the above copyright notice, this
 *     list of conditions and the following disclaimer.
 *
 *  2. Redistribution in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *
 *  3. Neither the name of the copyright holder nor the names of its contributors
 *     may be used to endorse or promote products derived from this software without
 *     specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * You acknowledge that this software is not designed, licensed or intended for use
 * in the design, construction, operation or maintenance of any military facility.
 */

import * as ByteBuffer from 'bytebuffer'

import { PublicKey } from '../crypto'
import { Asset } from './asset'

export interface AuthorityType {
  weight_threshold: number // uint32_t
  account_auths: [string, number][] // flat_map< account_name_type, uint16_t >
  key_auths: [string | PublicKey, number][] // flat_map< public_key_type, uint16_t >
}

export class Authority implements AuthorityType {
  public weight_threshold: number
  public account_auths: [string, number][]
  public key_auths: [string | PublicKey, number][]

  constructor({ weight_threshold, account_auths, key_auths }: AuthorityType) {
    this.weight_threshold = weight_threshold
    this.account_auths = account_auths
    this.key_auths = key_auths
  }

  /**
   * Convenience to create a new instance from PublicKey or authority object.
   */
  public static from(value: string | PublicKey | AuthorityType) {
    if (value instanceof Authority) {
      return value
    } else if (typeof value === 'string' || value instanceof PublicKey) {
      return new Authority({
        account_auths: [],
        key_auths: [[value, 1]],
        weight_threshold: 1
      })
    } else {
      return new Authority(value)
    }
  }
}

export interface Account {
  id: number // account_id_type
  name: string // account_name_type
  owner: Authority
  active: Authority
  posting: Authority
  memo_key: string // public_key_type
  json_metadata: string
  proxy: string // account_name_type
  last_owner_update: string // time_point_sec
  last_account_update: string // time_point_sec
  created: string // time_point_sec
  mined: boolean
  owner_challenged: boolean
  active_challenged: boolean
  last_owner_proved: string // time_point_sec
  last_active_proved: string // time_point_sec
  recovery_account: string // account_name_type
  reset_account: string // account_name_type
  last_account_recovery: string // time_point_sec
  comment_count: number // uint32_t
  lifetime_vote_count: number // uint32_t
  post_count: number // uint32_t
  can_vote: boolean
  voting_power: number // uint16_t
  last_vote_time: string // time_point_sec
  voting_manabar: {
    current_mana: string | number
    last_update_time: number
  }
  balance: string | Asset
  savings_balance: string | Asset
  hbd_balance?: string | Asset
  hbd_seconds?: string // uint128_t
  hbd_seconds_last_update?: string // time_point_sec
  hbd_last_interest_payment?: string // time_point_sec
  savings_hbd_balance?: string | Asset // asset
  savings_hbd_seconds?: string // uint128_t
  savings_hbd_seconds_last_update?: string // time_point_sec
  savings_hbd_last_interest_payment?: string // time_point_sec
  sbd_balance?: string | Asset // remove after hf24
  sbd_seconds?: string // uint128_t // remove after hf24
  sbd_seconds_last_update?: string // time_point_sec // remove after hf24
  sbd_last_interest_payment?: string // time_point_sec // remove after hf24
  savings_sbd_balance?: string | Asset // asset // remove after hf24
  savings_sbd_seconds?: string // uint128_t // remove after hf24
  savings_sbd_seconds_last_update?: string // time_point_sec // remove after hf24
  savings_sbd_last_interest_payment?: string // time_point_sec // remove after hf24
  savings_withdraw_requests: number // uint8_t
  reward_hbd_balance?: string | Asset
  reward_hive_balance?: string | Asset
  reward_sbd_balance?: string | Asset // remove after hf24
  reward_steem_balance?: string | Asset // remove after hf24
  reward_vesting_balance: string | Asset
  reward_vesting_hive?: string | Asset
  reward_vesting_steem?: string | Asset // remove after hf24
  curation_rewards: number | string // share_type
  posting_rewards: number | string // share_type
  vesting_shares: string | Asset
  delegated_vesting_shares: string | Asset
  received_vesting_shares: string | Asset
  vesting_withdraw_rate: string | Asset
  next_vesting_withdrawal: string // time_point_sec
  withdrawn: number | string // share_type
  to_withdraw: number | string // share_type
  withdraw_routes: number // uint16_t
  proxied_vsf_votes: number[] // vector< share_type >
  witnesses_voted_for: number // uint16_t
  average_bandwidth: number | string // share_type
  lifetime_bandwidth: number | string // share_type
  last_bandwidth_update: string // time_point_sec
  average_market_bandwidth: number | string // share_type
  lifetime_market_bandwidth: number | string // share_type
  last_market_bandwidth_update: string // time_point_sec
  last_post: string // time_point_sec
  last_root_post: string // time_point_sec
}

export interface ExtendedAccount extends Account {
  /**
   * Convert vesting_shares to vesting hive.
   */
  vesting_balance: string | Asset
  reputation: string | number // share_type
  /**
   * Transfer to/from vesting.
   */
  transfer_history: any[] // map<uint64_t,applied_operation>
  /**
   * Limit order / cancel / fill.
   */
  market_history: any[] // map<uint64_t,applied_operation>
  post_history: any[] // map<uint64_t,applied_operation>
  vote_history: any[] // map<uint64_t,applied_operation>
  other_history: any[] // map<uint64_t,applied_operation>
  witness_votes: string[] // set<string>
  tags_usage: string[] // vector<pair<string,uint32_t>>
  guest_bloggers: string[] // vector<pair<account_name_type,uint32_t>>
  open_orders?: any[] // optional<map<uint32_t,extended_limit_order>>
  comments?: any[] // / permlinks for this user // optional<vector<string>>
  blog?: any[] // / blog posts for this user // optional<vector<string>>
  feed?: any[] // / feed posts for this user // optional<vector<string>>
  recent_replies?: any[] // / blog posts for this user // optional<vector<string>>
  recommended?: any[] // / posts recommened for this user // optional<vector<string>>
}
